home *** CD-ROM | disk | FTP | other *** search
/ Aminet 8 / Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso / Aminet / comm / fido / NLFind.lha / NLFind / src.lha / NLFind.c < prev    next >
C/C++ Source or Header  |  1995-08-31  |  14KB  |  584 lines

  1. /***************************************************************************
  2.  * NLFind.c
  3.  *
  4.  * NLFind, Copyright ©1995 Lee Kindness.
  5.  *
  6.  * Patches:
  7.  *  traplist.library NLFind()
  8.  *  traplist.library NLIndexFind()
  9.  *
  10.  * This source is for example purposes...
  11.  *
  12.  */
  13.  
  14. /* This is version... */
  15. #define VERSION "1.2"
  16.  
  17. /* All our includes are in this file */
  18. #include "gst.c"
  19.  
  20. /* download dev/c/SFPatch.lha for documentation */ 
  21. #include "SFPatch.h"
  22.  
  23. /* Libraries used, don't auto open them SAS/C :) */
  24. extern struct IntuitionBase *IntuitionBase = NULL;
  25. extern struct Library *CxBase = NULL;
  26. struct Library *NodelistBase = NULL;
  27.  
  28. /* Save a bit of typing */
  29. #define REG(x) register __ ## x
  30.  
  31. /* Library Vector Offsets */
  32. #define NLF_OFFSET -48
  33. #define NLIF_OFFSET -66
  34.  
  35. typedef NodeDesc * __asm (*NLF_Caller)( REG(a0) NodeList,
  36.                                         REG(a1) Addr *,
  37.                                         REG(d0) ULONG, 
  38.                                         REG(a6) struct Library *);
  39.  
  40. typedef NodeDesc * __asm (*NLIF_Caller)( REG(a0) NodeList,
  41.                                          REG(a1) Addr *,
  42.                                          REG(d0) ULONG, 
  43.                                          REG(a6) struct Library *);
  44.  
  45. /* We alloc one of these per MULTILINE entry in the cfg file */
  46. struct MLNode 
  47. {
  48.     struct MLNode *ml_Succ;        /* Next MLNode */
  49.     struct MLNode *ml_Pred;        /* Previous MLNode */
  50.     UBYTE          ml_reserved1;   /* unused nl_Type */
  51.     BYTE           ml_Flags;       /* Option flags  */
  52.     STRPTR         ml_ReplaceWith; /* text array of subsitutes */
  53.     Addr           ml_BaseNode;    /* The node this MLNode deals with */
  54.     STRPTR         ml_Last;        /* Last number/node used */
  55. };
  56.  
  57. /* Flags for ml_Flags */
  58. #define MLFB_COPYPASS 0
  59. #define MLFF_COPYPASS 1
  60.  
  61. /* Constants for ml_Last */
  62. #define MLLAST_NONE (STRPTR)~0
  63. #define MLLAST_BASENODE NULL
  64.  
  65. /* To hold all the MLNodes */
  66. struct MLList 
  67. {
  68.     struct MLNode *mllh_Head;
  69.     struct MLNode *mllh_Tail;
  70.     struct MLNode *mllh_TailPred;
  71. };
  72.  
  73. /* Prototypes */
  74. NodeDesc * __asm NLF_New( REG(a0) NodeList,
  75.                           REG(a1) Addr *,
  76.                           REG(d0) ULONG, 
  77.                           REG(a6) struct Library *);
  78.  
  79. NodeDesc * __asm NLIF_New( REG(a0) NodeList,
  80.                            REG(a1) Addr *,
  81.                            REG(d0) ULONG, 
  82.                            REG(a6) struct Library *);
  83.  
  84. BOOL OpenLibs(void);
  85. void CloseLibs(void);
  86. BOOL ShowWindow(void);
  87. LONG OpenCfg(STRPTR filename);
  88.  
  89. /* Global vars */
  90. SetFunc *NLF_SetFunc, *NLIF_SetFunc;
  91. struct Remember *grk;
  92. BOOL Active;
  93. struct MLList *mlines;
  94. char vertag[] = "$VER: NLFind "VERSION" "__AMIGADATE__;
  95.  
  96. #define DEF_CFGFILE "MAIL:MultiLine.cfg"
  97.  
  98.  
  99. /***************************************************************************
  100.  * main() --
  101.  */
  102. int main(int argc, char **argv)
  103. {
  104.     int ret = RETURN_FAIL;
  105.     Active = TRUE;
  106.     grk = NULL;
  107.     
  108.     /* check version */
  109.     if (OpenLibs()) 
  110.     {
  111.         struct NewBroker nb = 
  112.         {
  113.             NB_VERSION,
  114.             "NLFind",
  115.             &vertag[6],
  116.             "Gives traplist.library multiline support",
  117.             NBU_UNIQUE | NBU_NOTIFY,
  118.             COF_SHOW_HIDE,
  119.             -1,
  120.             NULL,
  121.             0
  122.         };
  123.         CxObj *broker;
  124.         nb.nb_Pri = 0;
  125.                 
  126.         if ((nb.nb_Port = CreateMsgPort()) && (broker = CxBroker(&nb, NULL))) 
  127.         {
  128.             STRPTR filename;
  129.         
  130.             if( argc == 2 )
  131.                 filename = argv[1];
  132.             else
  133.                 filename = DEF_CFGFILE;
  134.             
  135.             if( OpenCfg(filename) )
  136.             {
  137.                 /* Alloc our SetFunc's */
  138.                 if( (NLF_SetFunc = AllocVec(sizeof(SetFunc), MEMF_CLEAR)) &&
  139.                     (NLIF_SetFunc = AllocVec(sizeof(SetFunc), MEMF_CLEAR)) ) 
  140.                 {
  141.                     /* init. sfs */
  142.                     NLF_SetFunc->sf_Func = NLF_New;
  143.                     NLF_SetFunc->sf_Library = NodelistBase;
  144.                     NLF_SetFunc->sf_Offset = NLF_OFFSET;
  145.                     NLF_SetFunc->sf_QuitMethod = SFQ_COUNT;
  146.                     NLIF_SetFunc->sf_Func = NLIF_New;
  147.                     NLIF_SetFunc->sf_Library = NodelistBase;
  148.                     NLIF_SetFunc->sf_Offset = NLIF_OFFSET;
  149.                     NLIF_SetFunc->sf_QuitMethod = SFQ_COUNT;
  150.  
  151.                     /* Replace the functions */
  152.                     if ( (SFReplace(NLF_SetFunc)) &&
  153.                          (SFReplace(NLIF_SetFunc)) ) 
  154.                     {
  155.                         ULONG sig, sret;
  156.                         BOOL finished;
  157.                     
  158.                         ActivateCxObj(broker, 1L);
  159.  
  160.                         ret = RETURN_OK;
  161.                         
  162.                         finished = FALSE;
  163.                         sig = 1 << nb.nb_Port->mp_SigBit;
  164.                     
  165.                         do 
  166.                         {
  167.                             sret = Wait(SIGBREAKF_CTRL_C | sig);
  168.                             if (sret & sig) 
  169.                             {
  170.                                 CxMsg *msg;
  171.                                 while(msg = (CxMsg *)GetMsg(nb.nb_Port)) 
  172.                                 {
  173.                                     switch(CxMsgType(msg)) 
  174.                                     {
  175.                                         case CXM_COMMAND:
  176.                                             switch(CxMsgID(msg)) 
  177.                                             {
  178.                                                 case CXCMD_DISABLE:
  179.                                                     ActivateCxObj(broker, 0L);
  180.                                                     Active = FALSE;
  181.                                                     break;
  182.                                                 case CXCMD_ENABLE:
  183.                                                     ActivateCxObj(broker, 1L);
  184.                                                     Active = TRUE;
  185.                                                     break;
  186.                                                 case CXCMD_KILL:
  187.                                                     finished = TRUE;
  188.                                                     break;
  189.                                                 case CXCMD_UNIQUE:
  190.                                                     finished = ShowWindow();
  191.                                                     break;
  192.                                                 case CXCMD_APPEAR:
  193.                                                     finished = ShowWindow();
  194.                                                     break;
  195.                                             }
  196.                                             break;
  197.                                     }
  198.                                     ReplyMsg((struct Message *)msg);
  199.                                 }
  200.                             }
  201.                             if (sret & SIGBREAKF_CTRL_C)
  202.                                 finished = TRUE;
  203.                         } while (!finished);
  204.                         ActivateCxObj(broker, 0L);
  205.         
  206.                         /* Restore functions */
  207.                         SFRestore(NLIF_SetFunc);
  208.                         SFRestore(NLF_SetFunc);
  209.                     }
  210.                     FreeVec(NLF_SetFunc);    
  211.                 }
  212.             }
  213.             DeleteCxObj(broker);
  214.             DeletePort(nb.nb_Port);
  215.         }
  216.         FreeRemember(&grk, TRUE);
  217.     }
  218.     CloseLibs();
  219.     return(ret);
  220. }
  221.  
  222.  
  223. /***************************************************************************
  224.  * OpenCfg() -- Read in the preferences file.
  225.  */
  226. #define MULTILINE_TEMP "MULTILINE/A/K,COPYPASS=COPYPASSWD/S,AKA/F/A"
  227. #define OPT_NODE 0
  228. #define OPT_COPYPASS 1
  229. #define OPT_AKA 2
  230. #define OPT_MAX 3
  231. #define BUF_SIZE 1000
  232.  
  233. LONG OpenCfg(STRPTR filename)
  234. {
  235.     LONG nodesadded = 0;
  236.     if( mlines = AllocRemember(&grk, sizeof(struct MLList), MEMF_CLEAR) )
  237.     {
  238.         STRPTR buf;
  239.         NewList((struct List *)mlines);
  240.     
  241.         if( buf = AllocVec(BUF_SIZE, 0) )
  242.         {
  243.             BPTR file;
  244.             if( file = Open(filename, MODE_OLDFILE) )
  245.             {
  246.                 struct RDArgs *rda;
  247.                 if( rda = AllocDosObject(DOS_RDARGS, NULL) )
  248.                 {
  249.                     STRPTR nbuf;
  250.                     STRPTR args[OPT_MAX];
  251.                     rda->RDA_DAList = NULL;
  252.                     rda->RDA_Flags |= RDAF_NOPROMPT;
  253.                     for( nbuf = FGets(file, buf, BUF_SIZE-1); nbuf; nbuf = FGets(file, buf, BUF_SIZE-1) )
  254.                     {
  255.                         if( (nbuf[0] == 'm') || (nbuf[0] == 'M') )
  256.                         {
  257.                             rda->RDA_Buffer = NULL;
  258.                             rda->RDA_Source.CS_Buffer = nbuf;
  259.                             rda->RDA_Source.CS_Length = strlen(nbuf);
  260.                             rda->RDA_Source.CS_CurChr = 0;
  261.                             args[0] = NULL;
  262.                             args[1] = NULL;
  263.                             args[2] = NULL;
  264.                         
  265.                             if( ReadArgs(MULTILINE_TEMP, (LONG *)&args, rda)) 
  266.                             {
  267.                                 struct MLNode *mln;
  268.                                 /* Allocate a node */
  269.                                 if( mln = AllocRemember(&grk, sizeof(struct MLNode), MEMF_CLEAR) )
  270.                                 {
  271.                                     /* Parse the Addr */
  272.                                     if( !NLParseAddr(&mln->ml_BaseNode, args[OPT_NODE], NULL) )
  273.                                     {
  274.                                         /* Alloc memory for mln->ml_ReplaceWith */
  275.                                         if( mln->ml_ReplaceWith = AllocRemember(&grk, strlen(args[OPT_AKA])+1, 0) )
  276.                                         {
  277.                                             /* Copy replacements */
  278.                                             strcpy(mln->ml_ReplaceWith, args[OPT_AKA]);
  279.                                         
  280.                                             /* Should we copy the password? */
  281.                                             if( args[OPT_COPYPASS] )
  282.                                                 mln->ml_Flags |= MLFF_COPYPASS;
  283.                                         
  284.                                             /* This node has never been selected... */
  285.                                             mln->ml_Last = MLLAST_NONE;
  286.                                         
  287.                                             /* Add node to list */
  288.                                             AddTail((struct List *)mlines, (struct Node *)mln);
  289.                                             nodesadded++;
  290.                                         }
  291.                                     }
  292.                                 }
  293.                                 FreeArgs(rda);
  294.                             }
  295.                         }
  296.                     } 
  297.                     FreeDosObject(DOS_RDARGS, rda);
  298.                 }
  299.                 Close(file);
  300.             }
  301.             FreeVec(buf);
  302.         }
  303.     }
  304.     return nodesadded;
  305. }
  306.  
  307.  
  308. /***************************************************************************
  309.  * ShowWindow() -- Show our window... currently only a requester 
  310.  */
  311. BOOL ShowWindow(void)
  312. {
  313.     struct EasyStruct ez = {
  314.         sizeof(struct EasyStruct),
  315.         0,
  316.         "NLFind",
  317.         "%s ©Lee Kindness.\n\n"
  318.         "Internet: wangi@fido.zetnet.co.uk\n"
  319.         "Fidonet: 2:259/26.20\n\n"
  320.         "MultiLine node support for traplist.library\n\n"
  321.         "Read \"NLFind.guide\" for more information\n\n"
  322.         "(Program may take a couple of seconds to quit)",
  323.         "Quit|Hide"
  324.     };
  325.     return((BOOL)EasyRequest(NULL, &ez, NULL, &vertag[6]));
  326. }
  327.  
  328.  
  329. /***************************************************************************
  330.  * OpenLibs() -- Open all used libraries
  331.  */
  332. BOOL OpenLibs(void)
  333. {
  334.     BOOL ret;
  335.     IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37);
  336.     CxBase = OpenLibrary("commodities.library", 37);
  337.     NodelistBase = OpenLibrary("traplist.library", 0);
  338.     ret = ((IntuitionBase) && 
  339.            (CxBase) && 
  340.            (NodelistBase));
  341.     return(ret);
  342. }
  343.  
  344.  
  345. /***************************************************************************
  346.  * CloseLibs() -- Close all libraries
  347.  */
  348. void CloseLibs(void)
  349. {
  350.     if (NodelistBase)
  351.         CloseLibrary(NodelistBase);
  352.     if (CxBase)
  353.         CloseLibrary(CxBase);
  354.     if (IntuitionBase)
  355.         CloseLibrary((struct Library *)IntuitionBase);
  356. }
  357.  
  358.  
  359. /***************************************************************************
  360.  * BumpPhone() -- Select the next pnone number
  361.  */
  362. NodeDesc *BumpPhone(NodeList nl, NodeDesc *nd, struct MLNode *mln, SetFunc *setfunc)
  363. {
  364.     #define BREAKCHARS "\t "
  365.     STRPTR s;
  366.     if( mln->ml_Last )
  367.         /* Skip to the next value in the string */
  368.         s = strpbrk(mln->ml_Last, BREAKCHARS);
  369.     else
  370.         /* Start at the begining */
  371.         s = mln->ml_ReplaceWith;
  372.     if( s )
  373.     {
  374.         STRPTR s2, s3;
  375.         BOOL pnum, fail;
  376.         LONG count;
  377.         fail = FALSE;
  378.         /* Skip white space */
  379.         s = stpblk(s);
  380.         
  381.         /* Find end of this item */
  382.         if( s2 = strpbrk(s, BREAKCHARS) )
  383.         {
  384.             /* Wow long is this item? and is it a phone number? */
  385.             pnum = TRUE;
  386.             count = 0;
  387.             s3 = s;
  388.             while( s3 != s2 )
  389.             {
  390.                 if( *s3 == ':' )
  391.                     /* its not a phone number */
  392.                     pnum = FALSE;
  393.                 count++;
  394.                 s3++;
  395.             }
  396.         } else
  397.         {
  398.             count = strlen(s);
  399.             if( strchr(s, ':') )
  400.                 pnum = FALSE;
  401.             else
  402.                 pnum = TRUE;
  403.         }
  404.         
  405.         /* If its a phone number then copy it into nd->Phone if the same size! */
  406.         if( pnum )
  407.         {
  408.             if( count <= strlen(nd->Phone) )
  409.                 strncpy(nd->Phone, s, count);
  410.             else
  411.                 fail = TRUE;
  412.         } else
  413.         {
  414.             STRPTR fqfa;
  415.             /* it is a FQFA */
  416.             if( fqfa = AllocVec(count+1, 0) )
  417.             {
  418.                 Addr *addr;
  419.                 strncpy(fqfa, s, count);
  420.                 if( addr = AllocVec(sizeof(Addr), MEMF_CLEAR) )
  421.                 {
  422.                     if( !NLParseAddr(addr, fqfa, NULL) )
  423.                     {
  424.                         NLF_Caller Caller;
  425.                         NodeDesc *nodedesc;
  426.                         /* Call NLFind#?() to resolve the phone number */
  427.                         Caller = (APTR)setfunc->sf_OriginalFunc;
  428.                         if( nodedesc = Caller(nl, addr, 0, NodelistBase) )
  429.                         {
  430.                             NodeDesc *temp;
  431.                             Addr tempaddr;
  432.                             
  433.                             temp = nodedesc;
  434.                             nodedesc = nd;
  435.                             nd = temp;
  436.                             
  437.                             tempaddr = nodedesc->Node;
  438.                             nodedesc->Node = nd->Node;
  439.                             nd->Node = tempaddr;
  440.                             
  441.                             if( (mln->ml_Flags & MLFF_COPYPASS) &&
  442.                                 (nodedesc->Passwd) &&
  443.                                 (nd->Passwd) )
  444.                             {
  445.                                 STRPTR temps;
  446.                                 temps = nodedesc->Passwd;
  447.                                 nodedesc->Passwd = nd->Passwd;
  448.                                 nd->Passwd = temps;
  449.                             }
  450.                             
  451.                             NLFreeNode(nodedesc);
  452.                         } else
  453.                             fail = TRUE;
  454.                     } else
  455.                         fail = TRUE;
  456.                     FreeVec(addr);
  457.                 } else
  458.                     fail = TRUE;
  459.                 FreeVec(fqfa);
  460.             } else
  461.                 fail = TRUE;
  462.         }
  463.         if( fail )
  464.             /* We are leaving ret->Phone as it is */
  465.             mln->ml_Last = MLLAST_BASENODE;
  466.         else
  467.             /* Update ml_Last */
  468.             mln->ml_Last = s;
  469.     } else
  470.         /* We are leaving ret->Phone as it is */
  471.         mln->ml_Last = MLLAST_BASENODE;
  472.     return nd;
  473. }
  474.  
  475.  
  476. /***************************************************************************
  477.  * NLF_New() -- The NLFind() replacement
  478.  */
  479. NodeDesc * __saveds __asm NLF_New( REG(a0) NodeList nl,
  480.                                    REG(a1) Addr *find_me,
  481.                                    REG(d0) ULONG flags,
  482.                                    REG(a6) struct Library *lib)
  483. {
  484.     NLF_Caller Caller;
  485.     NodeDesc *ret;
  486.     
  487.     /* increment count */
  488.     Forbid();
  489.     NLF_SetFunc->sf_Count += 1;
  490.     Permit();
  491.     
  492.     Caller = (APTR)NLF_SetFunc->sf_OriginalFunc;
  493.     
  494.     /* Pass the buck */
  495.     /* only do our stuff if we are an active cx and if NL_VERBATIM is not set */
  496.     if( (ret = Caller(nl, find_me, flags, lib)) &&
  497.         (Active) &&
  498.         !(flags & NL_VERBATIM) )
  499.     {
  500.         struct MLNode *mln, *foundnode;
  501.         
  502.         /* Go thru our list of mlines, looking for a match */
  503.         mln = mlines->mllh_Head;
  504.         while( mln->ml_Succ ) 
  505.         {
  506.             if( !NLAddrComp(&ret->Node, &mln->ml_BaseNode) )
  507.                 foundnode = mln;
  508.             mln = mln->ml_Succ;
  509.         }
  510.         if (foundnode) 
  511.         {
  512.             if( foundnode->ml_Last == MLLAST_NONE )
  513.                 /* Use ret->Phone as it is, and update ml_Last */
  514.                 foundnode->ml_Last = MLLAST_BASENODE;
  515.             else
  516.                 /* Get the next phone number */
  517.                 ret = BumpPhone(nl, ret, foundnode, NLF_SetFunc);
  518.         }
  519.     }
  520.     
  521.     /* decrement count */
  522.     Forbid();
  523.     NLF_SetFunc->sf_Count -= 1;
  524.     Permit();
  525.     
  526.     /* and return */
  527.     return(ret);
  528. }
  529.  
  530. /***************************************************************************
  531.  * NLIF_New() -- The NLIndexFind() replacement
  532.  */
  533. NodeDesc * __saveds __asm NLIF_New( REG(a0) NodeList nl,
  534.                                     REG(a1) Addr *find_me,
  535.                                     REG(d0) ULONG flags,
  536.                                     REG(a6) struct Library *lib)
  537. {
  538.     NLIF_Caller Caller;
  539.     NodeDesc *ret;
  540.     
  541.     /* increment count */
  542.     Forbid();
  543.     NLIF_SetFunc->sf_Count += 1;
  544.     Permit();
  545.     
  546.     Caller = (APTR)NLIF_SetFunc->sf_OriginalFunc;
  547.     
  548.     /* Pass the buck */
  549.     /* only do our stuff if we are an active cx and if NL_VERBATIM is not set */
  550.     if( (ret = Caller(nl, find_me, flags, lib)) &&
  551.         (Active) &&
  552.         !(flags & NL_VERBATIM) )
  553.     {
  554.         struct MLNode *mln, *foundnode;
  555.         
  556.         /* Go thru our list of mlines, looking for a match */
  557.         mln = mlines->mllh_Head;
  558.         while( mln->ml_Succ ) 
  559.         {
  560.             if( !NLAddrComp(&ret->Node, &mln->ml_BaseNode) )
  561.                 foundnode = mln;
  562.             mln = mln->ml_Succ;
  563.         }
  564.         if (foundnode) 
  565.         {
  566.             if( foundnode->ml_Last == MLLAST_NONE )
  567.                 /* Use ret->Phone as it is, and update ml_Last */
  568.                 foundnode->ml_Last = MLLAST_BASENODE;
  569.             else
  570.                 /* Get the next phone number */
  571.                 ret = BumpPhone(nl, ret, foundnode, NLIF_SetFunc);
  572.         }
  573.     }
  574.     
  575.     /* decrement count */
  576.     Forbid();
  577.     NLIF_SetFunc->sf_Count -= 1;
  578.     Permit();
  579.     
  580.     /* and return */
  581.     return(ret);
  582. }
  583.  
  584.